<?php
/**
 * Created by PhpStorm.
 * User: ari
 * Date: 10/6/14
 * Time: 2:30 PM
 */
namespace BC\Games\Holdem;

use BC\Games\Holdem\Exceptions\EndOfDeckException;
use BC\Games\Holdem\Exceptions\InvalidReplayException;

class Deck
{

	private $mCards = array();
	private $mGroups = array();
	private $mDrawPos = 0;
	private $mLastDrawnCard = null;

	public function __construct() {
		for ($n = Cards::TWO; $n <= Cards::ACE; $n += Cards::NUMBER_DIV) {
			for ($s = Cards::CLUBS; $s <= Cards::SPADES; $s += 1) {
				$p = sizeof($this->mCards);
				$r = mt_rand(0, $p);
				if ($r === $p) {
					$this->mCards[$r] = $n | $s;
				} else {
					$this->mCards[$p] = $this->mCards[$r];
					$this->mCards[$r] = $n | $s;
				}
			}
		}

		$total = array_sum($this->mCards);
		if($total !== Cards::TOTAL)
			throw new \Exception("Deck failed to add up to " . Cards::TOTAL);
	}

	function replay($replayCard, $stack) {
		if(!is_int($replayCard))
			throw new \InvalidArgumentException("Replay card was not an integer");
		if($this->mLastDrawnCard === $replayCard) {
			if(!in_array($replayCard, $this->getDrawnCards($stack)))
				throw new InvalidReplayException("Replayed card mismatch: " . $stack);
			$this->mLastDrawnCard = null;
			return;
		}
		$pos = array_search($replayCard, $this->mCards, true);
		if($pos === false) {
			throw new InvalidReplayException("Card not found in deck: " . $replayCard); }

		if($pos < $this->mDrawPos)
			throw new InvalidReplayException("Card already drawn: " . $replayCard);

		$drawPos = $this->mDrawPos++;

		$this->mGroups[$stack][] = $replayCard;

		if($drawPos === $pos)
			return;

		$this->mCards[$pos] = $this->mCards[$drawPos];
		$this->mCards[$drawPos] = $replayCard;
		return;
	}

	function draw($groupName) {
		if ($this->mDrawPos >= Cards::COUNT)
			throw new EndOfDeckException("No cards left in deck");

		$pos = $this->mDrawPos++;
		$card = $this->mCards[$pos];
		if($groupName)
			$this->mGroups[$groupName][] = $card;
		$this->mLastDrawnCard = $card;
		return $card;
	}

	function getDrawCount() {
		return $this->mDrawPos;
	}

	function hasGroup($groupName) {
		return isset($this->mGroups[$groupName]);
	}

	function getDrawnCards($groupName, $_groupName=null) {
		$cards = array();
		foreach(func_get_args() as $groupName) {
			if($groupName) {
				if(!isset($this->mGroups[$groupName]))
					throw new \InvalidArgumentException("Group does not exist: " . $groupName);
				else
					foreach($this->mGroups[$groupName] as $card)
						$cards[] = $card;
			}
		}
		return $cards;
	}

	function getCardCount($groupName) {
		return empty($this->mGroups[$groupName]) ? 0 : sizeof($this->mGroups[$groupName]);
	}

	function getCards() {
		return $this->mCards;
	}
}

